package com.tbit.utils;


import cn.hutool.core.date.DateTime;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.webmanager.util.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.pqc.crypto.newhope.NHOtherInfoGenerator;
import org.springframework.format.annotation.DateTimeFormat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;


@Slf4j
public class DateTimeUtil {
    // 用于存放不同模板的日期
    private static final ThreadLocal<Map<String, SimpleDateFormat>> LOCAL = new ThreadLocal<Map<String, SimpleDateFormat>>() {
        @Override
        protected Map<String, SimpleDateFormat> initialValue() {
            return new HashMap<String, SimpleDateFormat>();
        }
    };
    private static DateUtil sDay = DateUtil.YMD_;
    private static DateUtil sDay1 = DateUtil.YMD;
    private static DateUtil sDay2 = DateUtil.YM;
    private static DateUtil sDay10 = DateUtil.yyyyMMddHHmmss;
    private static DateUtil s = DateUtil.YMDHMS_;
    private static String forString = "yyyy-MM-dd HH:mm:ss";//格式化样本
    private static String YYYYMMDDHHSS = "yyyyMMddHHmm";
    private static String forString_YMD = "yyyy-MM-dd";//格式化样本
    private static String sDay3 = "yyyy-MM-dd";
    private static String MMDD = "MM月dd日";
    private static String YYYYMMDD = "yyyyMMdd";

    public static String format(Date date, DateUtil dateUtil) {
        return dateUtil.format(date);
    }

    /**
     * 获取当前时间
     */
    public static String getNowTime() {
        return s.format(new Date());
    }

    /**
     * 获取当前时间
     */
    public static String getNowTimeSDay() {
        return sDay.format(new Date());
    }


    public static String formatDateYMD(Date date) {
        return sDay.format(date);
    }

    /**
     * 获取当前时间num秒前的时间
     */
    public static String getBeforeTime(String data, Integer num) {
        try {
            Date date1 = s.parse(data);
            return s.format(date1.getTime() - num * 1000);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取当前时间num秒后的时间
     */
    public static String getLastTime(String data, Integer num) {
        try {
            Date date1 = s.parse(data);
            return s.format(date1.getTime() + num * 1000);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    @SuppressWarnings("AlibabaAvoidNewDateGetTime")
    public static String getNowTimeyyyyMMddHHmmss() {
        //noinspection AlibabaAvoidNewDateGetTime
        return DateUtils.parseDateToStr("yyyyMMddHHmmss", new Date(System.currentTimeMillis() + 61 * 1000));
    }

    /**
     * 获取当前时间
     */
    public static String getNowTimeyyyyMMdd() {
        return sDay1.format(new Date());
    }

    /**
     * 获取当前时间(yyyy-MM-dd)
     */
    public static String getNowTimeYMD() {
        return sDay.format(new Date());
    }


    /**
     * 获取指定时间年月
     */
    public static String getYYMM(String dateTime) {
        if (dateTime == null) {
            return sDay2.format(new Date());
        } else {
            try {
                return sDay2.format(sDay.parse(dateTime));
            } catch (ParseException e) {
                log.error(e.getMessage(), e);
            }

            return sDay2.format(new Date());
        }
    }

    /**
     * 获取指定时间段内每一天的日期
     */
    public static List<String> findDaysStr(String startTime, String endTime) {
        Date dBegin = null;
        Date dEnd = null;
        try {
            dBegin = sDay.parse(startTime);
            dEnd = sDay.parse(endTime);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        List<String> daysStrList = new ArrayList<>();
        daysStrList.add(sDay.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        calEnd.setTime(dEnd);
        while (dEnd.after(calBegin.getTime())) {
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            String dayStr = sDay.format(calBegin.getTime());
            daysStrList.add(dayStr);
        }
        return daysStrList;
    }

    /**
     * 获取指定时间段内每一天的日期
     */
    public static LinkedList<String> findDays(String startTime, String endTime) {
        Date dBegin = null;
        Date dEnd = null;
        try {
            dBegin = sDay.parse(startTime);
            dEnd = sDay.parse(endTime);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        LinkedList<String> daysStrList = new LinkedList<>();
        daysStrList.add(sDay.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        calEnd.setTime(dEnd);
        while (dEnd.after(calBegin.getTime())) {
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            String dayStr = sDay.format(calBegin.getTime());
            daysStrList.add(dayStr);
        }
        return daysStrList;
    }

    /**
     * 获取两个日期之间的所有月(字符串格式, 按月计算)
     *
     * @param
     * @param
     * @return
     */
    public static List<String> getMonthBetween(String minDate, String maxDate) throws ParseException {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        min.setTime(sdf.parse(minDate));
        min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

        max.setTime(sdf.parse(maxDate));
        max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }

        return result;
    }

    /**
     * 获取两个日期之间的所有月(字符串格式, 按月计算)
     *
     * @param start
     * @param end
     * @return
     */
    public static List<String> getBetweenMonths(Date start, Date end) {
        List<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");

        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(start);
        // 加了一个月
        tempStart.add(Calendar.MONTH, 1);
        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(end);
        result.add(sdf.format(start));
        while (tempStart.before(tempEnd)) {
            result.add(sdf.format(tempStart.getTime()));
            tempStart.add(Calendar.MONTH, 1);
        }
        return result;
    }

    /**
     * 指定日期加天数
     */
    public static Date addDay(Date dateTime, int days) {
        Calendar calender = Calendar.getInstance();
        calender.setTime(dateTime);
        calender.add(Calendar.DAY_OF_MONTH, days);
        return calender.getTime();
    }

    /**
     * 获取两个时间差
     */
    public static int getTime(String time1, String time2) {
        int time = 0;
        try {
            time = (int) ((s.parse(time2).getTime() - s.parse(time1).getTime()) / 1000);
        } catch (ParseException e) {
            log.error("时间转换出错", e);
        }
        return time;
    }

    public static int getNowTimeRange(String timeP) {
        int time = 0;
        try {
            time = (int) ((System.currentTimeMillis() - s.parse(timeP).getTime()) / 1000);
        } catch (ParseException e) {
            log.error("时间转换出错", e);
        }
        return time;
    }

    /**
     * 日期转字符串
     */
    public static Date StringToDateTime(String dateTime) {
        Date date = new Date();
        try {
            date = s.parse(dateTime);
        } catch (ParseException e) {
            log.error("时间转换出错", e);
        }
        return date;
    }

    /**
     * 字符串转日期类型
     */
    public static String DateTimeToString(Date d) {
        return s.format(d);
    }

    /**
     * 字符串转日期类型
     */
    public static String DateTimeToStringYMD(Date d) {
        return sDay.format(d);
    }

    /**
     * 日期获取当天
     */
    public static int getDayOfMonth(Date date) {
        Calendar c = new GregorianCalendar();
        c.setTime(date);
        return c.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取月份的天数
     */
    public static int getDayNumOfMonth(Date date) {
        Calendar c = new GregorianCalendar();
        c.setTime(date);
        //判断是不是当月
        Calendar c1 = new GregorianCalendar();
        c1.setTime(new Date());
        if (c.get(Calendar.YEAR) == c1.get(Calendar.YEAR) && c.get(Calendar.MONTH) == c1.get(Calendar.MONTH)) {
            return c1.get(Calendar.DAY_OF_MONTH);
        }
        return c.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 判断是和指定时间相差20min
     */
    public static boolean isInTwM(Date date, String s) {
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        boolean result = true;

        Calendar d = new GregorianCalendar();
        d.setTime(date);
        Date sd = new Date();
        try {
            sd = simple.parse(d.get(Calendar.YEAR) + "-" + (d.get(Calendar.MONTH) + 1) + "-" + d.get(Calendar.DATE) + " " + s);
        } catch (ParseException e) {
            log.error("时间转换异常", e);
        }

        Long dt = Math.abs(date.getTime() - sd.getTime());
        if (dt > 20 * 60 * 1000) {
            result = false;
        }

        return result;
    }

    /**
     * 根据时间区间求天数
     */
    public static int getDayCountByRange(String startDay, String endDay) {
        /* 如果是同一天 */
        if (startDay.equals(endDay)) {
            return 1;
        } else {
            int days = 0;
            try {
                days = (int) ((sDay.parse(endDay).getTime() - sDay.parse(startDay).getTime()) / (24 * 3600 * 1000) + 1);
            } catch (ParseException e) {
                log.error(e.getMessage(), e);
            }
            return days;
        }
    }

    /**
     * 根据时间区间求天数组
     */
    public static String[] getDays(String startDay, String endDay) {
        String days[] = new String[getDayCountByRange(startDay, endDay)];

        /* 是否只有一天 */
        int length = days.length;
        if (length == 1) {
            days[0] = startDay;
        } else {
            days[0] = startDay;
            for (int i = 1; i < length - 1; i++) {
                try {
                    days[i] = sDay.format(new Date(sDay.parse(startDay).getTime() + i * 24 * 3600 * 1000L));
                } catch (ParseException e) {
                    log.error(e.getMessage(), e);
                }
            }
            days[length - 1] = endDay;
        }

        return days;
    }

    /**
     * 指定日期加月份
     */
    public static Date addMonth(Date dateTime, int months) {
        Calendar calender = Calendar.getInstance();
        calender.setTime(dateTime);
        calender.add(Calendar.MONTH, months);
        return calender.getTime();
    }

    /**
     * @param: 入参是当前时间2020-02-29
     * @return:返参是后一天的日期,理应为2020-03-01
     */
    public static String getNextDay(String dateTime) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = simpleDateFormat.parse(dateTime);
        } catch (ParseException e) {
            log.error("String转Date日期失败:", e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //往后一天
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        return simpleDateFormat.format(calendar.getTime());
    }


    /**
     * 获取前一天的日期
     */
    public static String getYesterday() {
        Date dNow = new Date(); //当前时间
        Date dBefore = new Date();
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(dNow);//把当前时间赋给日历
        calendar.add(Calendar.DATE, -1); //前一天
        dBefore = calendar.getTime(); //得到前3月的时间
        return sDay.format(dBefore);
    }

    public static String getYesterdayTime() {
        Date dNow = new Date(); //当前时间
        Date dBefore = new Date();
        Calendar calendar = Calendar.getInstance(); //得到日历
        calendar.setTime(dNow);//把当前时间赋给日历
        calendar.add(Calendar.DATE, -1); //前一天
        dBefore = calendar.getTime(); //得到前3月的时间
        return s.format(dBefore);
    }

    public static Date getYesterdayHHMMSS(Integer amount) {
        return getYesterdayHHMMSS(amount, 23, 59, 59);
    }

    public static Date getYesterdayHHMMSS(Integer amount, int hour, int minute, int second) {
        Date today = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        //获取前几天的都可以，对-1进行改变即可
        //获取后一天的时间也可以，把-1改为1即可
        //后几天和前几天同理
        calendar.add(Calendar.DAY_OF_MONTH, amount);
        return calendar.getTime();
    }

    public static boolean isStartOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 将时间设置为当月的开始
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 判断是否为当月的第一天
        return calendar.getTime().equals(date);
    }

    public static boolean isStartOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 将时间设置为当月的开始
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        // 判断是否为当月的第一天
        return calendar.getTime().equals(date);
    }

    public static Date getYesterdayHHMMSS(String time, Integer amount) {
        Date today = null;
        try {
            today = sDay.parse(time);
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(today);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        //获取前几天的都可以，对-1进行改变即可
        //获取后一天的时间也可以，把-1改为1即可
        //后几天和前几天同理
        calendar.add(Calendar.DAY_OF_MONTH, amount);
        return calendar.getTime();
    }

    /**
     * 获取和当前的小时差
     */
    public static Integer getHour(String startTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            Integer baseHour = (int) (time / (60 * 60 * 1000));

            if (time % (60 * 60 * 1000) > 0) {
                baseHour++;
            }

            return baseHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    public static List<String> generateDateHourList(String startDateStr, String endDateStr,boolean plusHour) {
        List<String> dateHours = new ArrayList<>();
        DateTimeFormatter ymdFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");

        // 解析开始时间和结束时间
        LocalDateTime startDateTime = LocalDateTime.parse(startDateStr, dateTimeFormatter);
        LocalDateTime endDateTime = LocalDateTime.parse(endDateStr, dateTimeFormatter);

        LocalDateTime variableDate = startDateTime;
        int addHour = plusHour ? 1 : 0;
        while (variableDate.isBefore(endDateTime)) {
            dateHours.add(variableDate.format(ymdFormatter) + '_' + (variableDate.getHour() + addHour));
            variableDate = variableDate.plusHours(1);
        }
        return dateHours;
    }

    public static int getDiffSec(Date s, Date e) {
        return (int) ((e.getTime() - s.getTime()) / 1000);
    }

    public static double getDiffDay(Date s, Date e) {
        return ((e.getTime() - s.getTime()) / (1000.0 * 60 * 60 * 24));
    }

    /**
     * 获取和当前的小时差（需要减去临时停车的时长）
     */
    public static Integer getHour(String startTime, Integer stopTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            /**临时停车的时间为秒*/
            Long time = time2 - time1 - stopTime * 1000;

            Integer baseHour = (int) (time / (60 * 60 * 1000));

            if (time % (60 * 60 * 1000) > 0) {
                baseHour++;
            }

            return baseHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的自定义时长差（需要减去临时停车的时长）
     */
    public static Integer getByMI(String startTime, Integer stopTime, Double integer) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            /**临时停车的时间为秒*/
            Long time = time2 - time1 - stopTime * 1000;

            Integer baseHour = (int) (time / (integer * 60 * 1000));

            if (time % (60 * 60 * 1000) > 0) {
                baseHour++;
            }

            return baseHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的自定义时长差
     */
    public static Integer getByMI(String startTime, Double integer) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            Integer baseHour = (int) (time / (integer * 60 * 1000));

            if (time % (60 * 60 * 1000) > 0) {
                baseHour++;
            }

            return baseHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的半小时差
     */
    public static Integer getHalfHour(String startTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            Integer halfHour = (int) (time / (30 * 60 * 1000));

            if (time % (30 * 60 * 1000) > 0) {
                halfHour++;
            }

            return halfHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的半小时差
     */
    public static Integer getHalfHour(String startTime, Integer stopTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            Integer halfHour = (int) (time / (30 * 60 * 1000));

            if (time % (30 * 60 * 1000) > 0) {
                halfHour++;
            }

            return halfHour;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的分钟差
     */
    public static Integer getMinDiffer(String startTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            Integer minutes = (int) (time / (60 * 1000));

            if (time % (60 * 1000) > 0) {
                minutes++;
            }

            return minutes;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的分钟差
     */
    public static Integer getMinDiffer(String startTime, Integer stopTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            /**减去临时停车时长*/
            Long time = time2 - time1 - stopTime * 1000;

            Integer minutes = (int) (time / (60 * 1000));

            if (time % (60 * 1000) > 0) {
                minutes++;
            }

            return minutes;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 获取和当前的秒差
     */
    public static Integer getSecondDiffer(String startTime) {
        SimpleDateFormat s = new SimpleDateFormat(forString);
        try {
            Date date1 = s.parse(startTime);
            Date date2 = new Date();

            Long time1 = date1.getTime();
            Long time2 = date2.getTime();

            Long time = time2 - time1;

            return (int) (time / 1000);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return 0;
    }

    /**
     * 根据格林尼治时间格式化
     */
    public static String getDateTimeByGL(Long time) {
        return s.format(time);
    }


    public static List<String> getDateArrByMonth(Date startDate, Date endDate) {
        Calendar c = Calendar.getInstance();
        List<String> list = new ArrayList<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
        for (; startDate.getTime() <= endDate.getTime(); ) {
            String _startDate = df.format(startDate);
            list.add(_startDate);
            c.setTime(startDate);
            c.add(Calendar.MONTH, 1);    //加一个月
            startDate = c.getTime();

        }
        return list;
    }

    /**
     * 返回YYYYMMDDHHSS 格式数据
     *
     * @param
     * @return
     */
    public static String getYYYYMMDDHHSS() {
        SimpleDateFormat s = new SimpleDateFormat(YYYYMMDDHHSS);
        return s.format(new Date());
    }

    /**
     * 根据时间获取月份
     *
     * @param stDate  开始时间
     * @param endDate 结束时间
     * @return 返回结果
     */
    public static List<String> getMonth(String stDate, String endDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        try {
           return getDateArrByMonth(simpleDateFormat.parse(stDate), simpleDateFormat.parse(endDate));
        } catch (Exception e) {
            log.error("月{}-{}转换失败", stDate, endDate, e);
            throw new BaseException("时间转换失败");
        }
    }


    /**
     * 获取值得月份的日期
     */
    public static String getLastMonth(int month, String date) throws ParseException {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, month);
        if (!NullUtils.isEmpty(date)) {
            date = date + "-01";
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            c.setTime(formatter.parse(date));
            c.add(Calendar.MONTH, 1);
            c.set(Calendar.DAY_OF_MONTH, 0);
            String LastDate = formatter.format(c.getTime()) + " 23:59:59";
            return LastDate;
        }

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        return format.format(c.getTime());

    }


    public static final String getLastMonth() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        // 设置为当前时间
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -1);
        // 设置为上一个月
        //calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        date = calendar.getTime();
        return format.format(date);
    }

    public static final String getCurrentMonth(Integer tag) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        // 设置为当前时间
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, tag);
        // 设置为上一个月
        //calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        date = calendar.getTime();
        return format.format(date);
    }

    /**
     * 获取当前时间前半个小时的时间
     */
    public static String beforeOneHourToNowDate() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.MINUTE,
                calendar.get(Calendar.MINUTE) - 30);// 让日期加1
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }

    /**
     * 获取今天年月日的时间戳
     */
    public static Long getTodayTime() {
        Calendar todayStart = Calendar.getInstance();
        todayStart.set(Calendar.HOUR_OF_DAY, 0);
        todayStart.set(Calendar.MINUTE, 0);
        todayStart.set(Calendar.SECOND, 0);
        todayStart.set(Calendar.MILLISECOND, 0);
        return todayStart.getTime().getTime();
    }

    /**
     * 给指定时间加上指定时长
     */
    public static Date getDate(Date date, int hour, int minute) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 24小时制
        cal.add(Calendar.HOUR, hour);
        cal.add(Calendar.MINUTE, minute);
        return cal.getTime();
    }

    /**
     * 给指定时间加上指定时长,加年月日时分秒
     */
    public static Date getNewDate(Date date, int hour, int minute, int second) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 24小时制
        cal.add(Calendar.HOUR, hour);
        cal.add(Calendar.MINUTE, minute);
        cal.add(Calendar.SECOND, second);
        return cal.getTime();
    }

    /**
     * 给指定时间加上指定时长,加年月日时分秒
     */
    public static String addDate(String date, int month) throws ParseException {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
        Calendar cal = Calendar.getInstance();
        cal.setTime(simpleDateFormat.parse(date));
        // 24小时制
        cal.add(Calendar.MONTH, month);
        return simpleDateFormat.format(cal.getTime());
    }

    /**
     * 获取昨天开始时间和结束时间
     *
     * @return
     */
    public static String getYesterdayEndTime() {
        Long endTime = getEndDayOfYesterDay();
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String endTimeStr = ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(endTime), ZoneId.systemDefault()));
        return endTimeStr;
    }

    public static String getNowdayEndTime() {
        Long endTime = getEndDayOfNowDay();
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String endTimeStr = ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(endTime), ZoneId.systemDefault()));
        return endTimeStr;
    }

    public static Long getEndDayOfYesterDay() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.add(Calendar.DAY_OF_MONTH, -1);
        return cal.getTimeInMillis();
    }

    public static Long getEndDayOfNowDay() {
        Calendar cal = new GregorianCalendar();
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTimeInMillis();
    }

    /**
     * 转换成yyyyMMdd格式  预统计用
     *
     * @param date
     * @return
     */
    public static Integer parseDataDate(Date date) {
        return Integer.parseInt(cn.hutool.core.date.DateUtil.format(date, "yyyyMMdd"));
    }

    /**
     * 获取两个时间之间的每一天
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getBetweenEveryDay(Date startTime, Date endTime) {
        if (startTime == null || endTime == null || (startTime.getTime() > endTime.getTime())) {
            //防止死循环
            throw new BaseException("时间有误");
        }
        List<String> dateList = new LinkedList<>();
        long tempTime = startTime.getTime();
        long endTimeStamp = endTime.getTime();
        //一天的时间
        long oneDayStamp = 1000 * 60 * 60 * 24;
        while (tempTime <= endTimeStamp) {
            dateList.add(cn.hutool.core.date.DateUtil.formatDate(new Date(tempTime)));
            tempTime += oneDayStamp;
        }
        return dateList;
    }

    /**
     * 返回一个SimpleDateFormat,每个线程只会new一次pattern对应的sdf
     *
     * @param pattern
     * @return
     */
    private static SimpleDateFormat getSdf(String pattern) {
        Map<String, SimpleDateFormat> map = LOCAL.get();
        SimpleDateFormat sdf = map.get(pattern);
        if (sdf == null) {
            sdf = new SimpleDateFormat(pattern);
            map.put(pattern, sdf);
        }

        return sdf;
    }

    /**
     * 获取服务器截止日期
     *
     * @param startDate
     * @param
     * @return
     */
    public static String getServiceEndDate(String startDate, Integer type) {
        try {
            /**开始日期为空*/
            if (startDate == null) {
                startDate = getNowTimeYMD();
            }

            /**开始日期小于当前日期*/
            Long startTime = getSdf(sDay3).parse(startDate).getTime() + 24 * 3600 * 1000;
            if (startTime < System.currentTimeMillis()) {
                startDate = getNowTimeYMD();
            }

            /**在最新的时间上累加*/
            Calendar calender = Calendar.getInstance();
            calender.setTime(getSdf(sDay3).parse(startDate));
            if (type == 0) {//日
                calender.add(Calendar.DATE, 1);
            } else if (type == 1) {//周
                calender.add(Calendar.DATE, 7);
            } else if (type == 2) {//月
                calender.add(Calendar.MONTH, 1);
            } else if (type == 3) {//季
                calender.add(Calendar.MONTH, 3);
            } else if (type == 4) {//半年
                calender.add(Calendar.MONTH, 6);
            } else if (type == 5) {//年
                calender.add(Calendar.YEAR, 1);
            }

            return getSdf(sDay3).format(calender.getTime());
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
        }

        return null;
    }

    /**
     * 根据传入的时间获取日期
     */
    public static String getDateTimeyyyyMMdd(Date date) {
        return sDay10.format(date);
    }

    /**
     * 获取当前时间
     */
    public static String geTime(Date date) {
        SimpleDateFormat s = getSdf(forString);
        return s.format(date);
    }
    /**
     * @description: 获取传入时间字符串对应的年月的1日0时0分0秒
     * @author: mo.shanyong
     * @date: 2025/2/18 18:52
     * @param: dateStr 时间字符串
     * @return: java.lang.String
     */
    public static String getMonthFirstDateByDate(String dateStr){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(forString);
        LocalDateTime parse = LocalDateTime.parse(dateStr,formatter);
        LocalDateTime localDateTime = parse.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
        return formatter.format(localDateTime);
    }
    /**
     * @description: 获取指定时间往前指定数量的月数的0时0分0秒
     * @author: mo.shanyong
     * @date: 2025/2/18 19:25
     * @param: dateStr 时间字符串
     * @param: munMonth 传入时间的前多少个月
     * @return: java.lang.String
     */
    public static LocalDateTime getBeforeDateNumMonth(String dateStr,int munMonth){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(forString);
        LocalDateTime parse = LocalDateTime.parse(dateStr,formatter);
        return parse.minusMonths(munMonth).withHour(0).withMinute(0).withSecond(0);
    }
    /**
     * @description: 根据传入的时间字符串，获取LocalDateTime
     * @author: mo.shanyong
     * @date: 2025/2/18 19:32
     * @param: timeStr
     * @return: java.time.LocalDateTime
     */
    public static LocalDateTime getLocalDateTimeByTimeStr(String timeStr){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(forString);
        return LocalDateTime.parse(timeStr,formatter);
    }
    /**
     * @description: h获取时间字符串
     * @author: mo.shanyong
     * @date: 2025/2/18 19:34
     * @param: localDateTime
     * @return: java.lang.String
     */
    public static String getDateStrByLocalDateTime(LocalDateTime localDateTime){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(forString);
        return formatter.format(localDateTime);
    }

    /**
     * @description: 获取日期字符串
     * @author: mo.shanyong
     * @date: 2025/2/18 19:34
     * @param: localDateTime
     * @return: java.lang.String
     */
    public static String getYMDStrByLocalDateTime(LocalDateTime localDateTime){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(forString_YMD);
        return formatter.format(localDateTime);
    }
    /**
     * @description: 获取传入时间当天的23点59分59秒的时间
     * @author: mo.shanyong
     * @date: 2025/3/4 14:36
     * @param: date
     * @return: java.util.Date
     */
    public static Date getLastTimeOfDayByDate(Date date){
        SimpleDateFormat dateFormat = new SimpleDateFormat(forString_YMD);
        String dateStr = dateFormat.format(date) + " 23:59:59";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(forString);
        try {
            return simpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @description: 获取几月几日
     * @author: mo.shanyong
     * @date: 2025/3/4 14:07
     * @param: date
     * @return: java.lang.String
     */
    public static String getMDByDate(Date date){
        // 使用Calendar类获取月份和日
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        // 获取月份（注意：Calendar的月份是从0开始的，所以需要加1）
        int month = calendar.get(Calendar.MONTH) + 1;

        // 获取日
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return month + "月" + (day < 10 ? "0" : "") + day + "日";
    }
    /**
     * @description: 获取哪年几月几日
     * @author: mo.shanyong
     * @date: 2025/3/4 14:07
     * @param: date
     * @return: java.lang.String
     */
    public static String getYMDByDate(Date date){
        // 使用Calendar类获取月份和日
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //获取年
        int year = calendar.get(Calendar.YEAR);

        // 获取月份（注意：Calendar的月份是从0开始的，所以需要加1）
        int month = calendar.get(Calendar.MONTH) + 1;

        // 获取日
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        return year + "年" + (month < 10 ? "0" : "") + month + "月" + (day < 10 ? "0" : "") + day + "日";
    }
    /**
     * @description: 获取yyyyMMdd格式的日期
     * @author: mo.shanyong
     * @date: 2025/3/7 15:41
     * @param: date
     * @return: java.lang.Integer
     */
    public static Integer getyyyyMMddByDate(Date date) {
        String format = sDay1.format(date);
        return Integer.parseInt(format);
    }

    /**
     * 获取两个时间之间的每一天
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getYYMMBetweenEveryDay(Date startTime, Date endTime,boolean getYear) {
        if (startTime == null || endTime == null || (startTime.getTime() > endTime.getTime())) {
            //防止死循环
            throw new BaseException("时间有误");
        }
        List<String> dateList = new LinkedList<>();
        long tempTime = startTime.getTime();
        long endTimeStamp = endTime.getTime();
        //一天的时间
        long oneDayStamp = 1000 * 60 * 60 * 24;
        while (tempTime <= endTimeStamp) {
            dateList.add(getYear ? getYMDByDate(new Date(tempTime)) : getMDByDate(new Date(tempTime)));
            tempTime += oneDayStamp;
        }
        return dateList;
    }
    /**
     * @description: 根据20211001格式的日期时间获取M月D日的日期格式
     * @author: mo.shanyong
     * @date: 2025/3/10 13:40
     * @param: date
     * @return: java.lang.String
     */
    public static String getMMDDByDate(Integer date){
        try {
            Date parse = sDay1.parse(String.valueOf(date));
            return getMDByDate(parse);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }
    /**
     * @description: 返回年月日组成的数字
     * @author: mo.shanyong
     * @date: 2025/3/11 19:26
     * @param: localDate
     * @return: java.lang.Integer
     */
    public static Integer getyyyyMMddByLocateDate(LocalDate localDate){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDD);
        return Integer.parseInt(formatter.format(localDate));
    }
    /**
     * @description: 根据时间戳获取年月日时分秒的时间字符串
     * @author: mo.shanyong
     * @date: 2025/3/18 13:40
     * @param: timeStamp
     * @return: java.lang.String
     */
    public static String getTimeAllStrByTimeStamp(String timeStamp){
        if (StringUtils.isBlank(timeStamp)){
            return null;
        }
        Date date = new Date(Long.valueOf(timeStamp));
        return s.format(date);
    }
    /**
     * @description: 时间字符串转换date
     * @author: mo.shanyong
     * @date: 2025/4/21 11:09
     * @param: dateStr
     * @return: java.util.Date
     */
    public static Date getDateByDateStr(String dateStr){
        try {
            return s.parse(dateStr);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取骑行卡截止日期
     *
     * @param type
     * @return
     */
    public static Date getRideCardEndDate(Integer type,Integer days) {
        if (days == null){
            days = 0;
        }
        /**在最新的时间上累加*/
        Calendar calender = Calendar.getInstance();
        if (type == 0 ) {//日
            calender.add(Calendar.DATE, 1);
        } else if (type == 1) {//周
            calender.add(Calendar.DATE, 7);
        } else if (type == 2) {//月
            calender.add(Calendar.MONTH, 1);
        } else if (type == 3) {//季
            calender.add(Calendar.MONTH, 3);
        } else if (type == 4) {//季
            calender.add(Calendar.MONTH, 6);
        } else if (type == 5) {//年
            calender.add(Calendar.YEAR, 1);
        }else if (type == 6) {//固定有效日期
            calender.add(Calendar.DATE, days);
        }
        return calender.getTime();
    }


    /**
     * @description: 获取传入日期的 00:00:00
     * @author wangweibin
     * @date 2025/4/10
     * @param date
     * @return Date
     */
    public static Date getStartOfDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * @description: 获取传入日期的 23:59:59
     * @author wangweibin
     * @date 2025/4/10
     * @param date
     * @return Date
     */
    public static Date getEndOfDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 获取开始日期到结束日期之间的所有日期（包含起止），格式为 Integer yyyyMMdd，返回升序排列列表
     *
     * @param start 开始日期，格式为 yyyyMMdd
     * @param end   结束日期，格式为 yyyyMMdd
     * @return 所有日期的 Integer 列表（升序）
     */
    public static List<Integer> getDateRange(Integer start, Integer end) {
        List<Integer> result = new ArrayList<>();
        if (start == null || end == null || start > end) {
            return result;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(YYYYMMDD);
        LocalDate startDate = LocalDate.parse(start.toString(), formatter);
        LocalDate endDate = LocalDate.parse(end.toString(), formatter);
        while (!startDate.isAfter(endDate)) {
            result.add(Integer.parseInt(startDate.format(formatter)));
            startDate = startDate.plusDays(1);
        }
        return result;
    }

    public static void main(String[] args){
        System.out.println(isStartOfMonth(new DateTime("2024-01-01 00")));
        System.out.println(isStartOfMonth(new DateTime("2024-01-01 00:11:11")));
        System.out.println(isStartOfMonth(new DateTime("2024-01-02 00:22")));
        System.out.println(getDateRange(20231229, 20240103));
    }

}
